//
//  ZYPurchaseSaleman+IAP.m
//  Pods
//
//  Created by wu on 2020/9/3.
//

#import "ZYPurchaseSaleman+IAP.h"
#import "ZYPurchaseDelegate.h"
#import "ZYPurchaseDataBase.h"

#import <ZYNetwork/PJNetworkStation.h>
#import "ZYPurchaseTransactionModel.h"

@implementation ZYPurchaseSaleman (IAP)

// MARK: SKPaymentTransactionObserver  -交易结束
- (void)completeTransaction:(SKPaymentTransaction *)transaction{
    NSLog(@"IAP: 交易结束了---");
}

// 过滤交易数组
- (NSArray <SKPaymentTransaction *>*)filterTransactionArray:(NSArray <SKPaymentTransaction *>*)transaction{
    // 筛选并拿最新的交易信息
    NSMutableArray *zy_transaction = @[].mutableCopy;
    NSMutableArray *transactionIdArray = @[].mutableCopy;
    for (NSInteger idx = 0; idx < transaction.count; idx++) {
        SKPaymentTransaction *trans = transaction[idx];
//        NSString *preStr = [NSString stringWithFormat:@"IAP: restore 的第 %ld 条交易", idx];
//        self.logTransaction(preStr, trans);
        if (trans.originalTransaction && trans.originalTransaction.transactionIdentifier.zy_isValuable) {
            if (![transactionIdArray containsObject:trans.originalTransaction.transactionIdentifier]) {
                [transactionIdArray addObject:trans.originalTransaction.transactionIdentifier];
                [zy_transaction addObject:trans];
            } else {
                for (NSInteger temp_idx = zy_transaction.count-1; temp_idx >= 0; temp_idx--) {
                    SKPaymentTransaction *temp_trans = zy_transaction[temp_idx];
                    if ([temp_trans.originalTransaction.transactionIdentifier isEqualToString:trans.originalTransaction.transactionIdentifier]) {
                        double temp_timeStamp = [temp_trans.transactionDate timeIntervalSince1970];
                        double timeStamp = [trans.transactionDate timeIntervalSince1970];
                        if (timeStamp > temp_timeStamp) {
                            [zy_transaction replaceObjectAtIndex:temp_idx withObject:trans];
                        }
                        break;
                    }
                }
            }
        } else {
            [zy_transaction addObject:trans];
        }
    }
    
    // 去除已经校验过的收据
    for (NSInteger temp_idx = zy_transaction.count-1; temp_idx >= 0; temp_idx--) {
        SKPaymentTransaction *trans = zy_transaction[temp_idx];
        if (trans.transactionState != SKPaymentTransactionStateRestored) {
            continue;
        }
        
        double timeStamp = [trans.transactionDate timeIntervalSince1970];
        if (![self.database cacheTransactionIfNeeded:trans.transactionIdentifier
                                      originTransId:trans.originalTransaction.transactionIdentifier
                                          productId:trans.payment.productIdentifier
                                 transDateTimestamp:timeStamp]) {
            NSLog(@"IAP: 此交易已经校验过收据了： %@", trans.originalTransaction.transactionIdentifier);
            [self responseRestoreTransaction:trans];
            [zy_transaction removeObjectAtIndex:temp_idx];
            self.logRecord(@"下面这条收据校验被拦截");
        }
        self.logTransaction(@"IAP: 最新交易是", trans);
    }
    return zy_transaction;
}

// 重复购买回调
- (void)responseRestoreTransaction:(SKPaymentTransaction *)transaction{
    ZYPurchaseTransactionModel *tModel = [self transactionModelFromSKTransaction:transaction];
    if (tModel) {
        [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
        // 重复购买
        tModel.transactionStatus = ZYPurchaseTransactionStatus_RePurchase;
        [self.database updateTransactionModelStatus:tModel];
        
        [self responseTransactionStatusChangedInMainThread:tModel];
        NSDictionary *notifiUserInfo = @{@"error":@(0),
                                         @"status":@(tModel.transactionStatus),
                                         @"orderId":tModel.orderId,
                                         @"result":@"RePurchase"};
        [NSNotificationCenter.defaultCenter postNotificationName:ZYPurchaseTransactionStatusChanged_Notifi object:nil userInfo:notifiUserInfo];
        if ([self.currentTransaction.orderId isEqualToString:tModel.orderId]) {
            self.currentTransaction = nil;
        }
    }
}

// MARK: SKPaymentTransactionObserver  -交易状态更新
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transaction{
    if (transaction.count == 0) {
        return;
    }
    NSMutableArray *zy_transaction = [self filterTransactionArray:transaction];
    for (SKPaymentTransaction *transaction in zy_transaction) {
        // 查看交易是否是订阅类型
        if ([self isSubscribe:transaction] && transaction.transactionState == SKPaymentTransactionStateRestored) {
            if (self.restoreStatus != ZYPurchaseIAPRestoreStatus_Accessed) {
                BOOL isAsking = (self.restoreStatus == ZYPurchaseIAPRestoreStatus_Asking);
                self.restoreStatus = ZYPurchaseIAPRestoreStatus_Accessed;
                if (isAsking) {
                    dispatch_async(dispatch_get_main_queue(), ^{
                        if (self.transaction_delegate && [self.transaction_delegate respondsToSelector:@selector(restoreStatusAccessedChanged:)]) {
                            [self.transaction_delegate restoreStatusAccessedChanged:ZYPurchaseIAPRestoreStatus_Accessed];
                        }
                    });
                }
            }
            NSLog(@"IAP: 查询到数据后，restore ask 结束");
        }
    }
    if (zy_transaction.count == 0) {
        return;
    }
    
    dispatch_group_t group = dispatch_group_create();
    for (NSInteger idx = 0; idx < zy_transaction.count; idx++) {
        SKPaymentTransaction *trans = zy_transaction[idx];
        dispatch_group_enter(group);
        [self asynHandlerTransaction:trans complete:^{
            dispatch_group_leave(group);
        }];
    }
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        if (self.currentTransaction) {
            ZYPurchaseTransactionStatus curTransactionStatus = [self.database queryTransactionModelTransactionStatus:self.currentTransaction.orderId];
            if ((curTransactionStatus == ZYPurchaseTransactionStatus_Cancel) ||
                (curTransactionStatus == ZYPurchaseTransactionStatus_Fail) ||
                (curTransactionStatus == ZYPurchaseTransactionStatus_Success) ||
                (curTransactionStatus == ZYPurchaseTransactionStatus_ReceiptInvalid) ||
                (curTransactionStatus == ZYPurchaseTransactionStatus_RePurchase) ||
                (curTransactionStatus == ZYPurchaseTransactionStatus_BindByOthers) ||
                (curTransactionStatus == ZYPurchaseTransactionStatus_Restored)) {
                self.currentTransaction = nil;
                NSLog(@"IAP: 释放了当前交易模型");
            } else {
                NSLog(@"IAP: 还不能释放了当前交易模型 订单：%@ 状态： %ld", self.currentTransaction.orderId, curTransactionStatus);
            }
        }
    });
}

- (void)asynHandlerTransaction:(SKPaymentTransaction *)transaction complete:(dispatch_block_t)complete{
    self.logTransaction(@"IAP: Apple 交易状态更新了", transaction);
    NSString *logStr = @"IAP: Apple 交易状态更新了";
    logStr = [logStr stringByAppendingFormat:@"state: %ld, applicationUsername: %@", transaction.transactionState, transaction.payment.applicationUsername];
    NSLog(logStr);
    
    if (!complete) {
        return;
    }
    // 状态未确定，不用处理
    if (transaction.transactionState == SKPaymentTransactionStateDeferred) {
        complete();
        NSString *logString = [NSString stringWithFormat:@"交易状态未确定 t_id: %@, origin_t_id: %@", transaction.transactionIdentifier, transaction.originalTransaction.transactionIdentifier];
        self.logRecord(logString);
        return;
    }
    // 正在IAP支付中
    if (transaction.transactionState == SKPaymentTransactionStatePurchasing) {
        ZYPurchaseTransactionModel *tModel = [self transactionModelFromSKTransaction:transaction];
        if (tModel) {
            tModel.transactionStatus = ZYPurchaseTransactionStatus_Purchasing;
            [self.database updateTransactionModelStatus:tModel];
            
            [self responseTransactionStatusChangedInMainThread:tModel];
            NSDictionary *notifiUserInfo = @{@"error":@(0),
                                             @"status":@(tModel.transactionStatus),
                                             @"orderId":tModel.orderId,
                                             @"result":@"支付中"};
            [NSNotificationCenter.defaultCenter postNotificationName:ZYPurchaseTransactionStatusChanged_Notifi object:nil userInfo:notifiUserInfo];
            NSLog(@"IAP: 支付中");
        } else {
            // 无主交易的支付中（也可能是续费成功收据）结果建议也让后台记录，可以查询出所有支付失败、成功的日志
        }
        NSString *logString = [NSString stringWithFormat:@"正在支付中 t_id: %@, origin_t_id: %@", transaction.transactionIdentifier, transaction.originalTransaction.transactionIdentifier];
        self.logRecord(logString);
        complete();
        return;
    }
    // 支付失败
    if (transaction.transactionState == SKPaymentTransactionStateFailed) {
        NSString *err = @"未知";
        if (transaction.error) {
            err = transaction.error.description;
        }
        NSString *logString = [NSString stringWithFormat:@"支付失败 原因：%@ t_id: %@, origin_t_id: %@", err, transaction.transactionIdentifier, transaction.originalTransaction.transactionIdentifier];
        self.logRecord(logString);
        
        [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
        ZYPurchaseTransactionModel *tModel = [self transactionModelFromSKTransaction:transaction];
        if (tModel) {
            NSString *errorDes = @"支付失败";
            tModel.error = transaction.error.description;
            if (transaction.error.code == SKErrorPaymentCancelled) {
                tModel.transactionStatus = ZYPurchaseTransactionStatus_Cancel;
                errorDes = @"支付已取消";
            } else {
                tModel.transactionStatus = ZYPurchaseTransactionStatus_Fail;
            }
            if (transaction.error.userInfo && (transaction.error.userInfo.allKeys.count > 0)) {
                if ([transaction.error.userInfo.allKeys containsObject:NSUnderlyingErrorKey]) {
                    id errObj = transaction.error.userInfo[NSUnderlyingErrorKey];
                    if (errObj && [errObj isKindOfClass:[NSError class]]) {
                        if (((NSError *)errObj).code == 3029) {
                            tModel.transactionStatus = ZYPurchaseTransactionStatus_Cancel;
                            errorDes = @"支付已取消（3029: 需要付款信息）";
                        }
                    }
                }
            }
            [self.database updateTransactionModelStatus:tModel];
            NSLog(@"IAP: 有订单的支付失败");
            [self responseTransactionStatusChangedInMainThread:tModel];
            
            NSDictionary *notifiUserInfo = @{@"error":@(70098),
                                             @"status":@(tModel.transactionStatus),
                                             @"orderId":tModel.orderId,
                                             @"result":errorDes};
            [NSNotificationCenter.defaultCenter postNotificationName:ZYPurchaseTransactionStatusChanged_Notifi object:nil userInfo:notifiUserInfo];
            
            // 支付失败后通知后台完结此订单，仅用于搜集日志
            NSString *customerId = ZYPurchaseSaleman.defaultSaleman.customerId;
            NSString *customerToken = ZYPurchaseSaleman.defaultSaleman.customerToken;
            
            NSString *error_des = transaction.error.description;
            NSMutableDictionary *params = @{}.mutableCopy;
            params[@"userid"] = customerId?customerId:@"";
            params[@"user_token"] = customerToken?customerToken:@"";
            params[@"orderSN"] = tModel.orderId.zy_isValuable?tModel.orderId:@"";
            params[@"reason"] = error_des.zy_isValuable?error_des:@"Unknown failure!";
            [PJNetworkStation POST:ZYPurchaseSaleman.formatPurchageUrlString(ZYPurchaseAPI_PayFailure) params:params result:^(BOOL success, id info) {
                
            }];
            
        } else {
            // 无主交易（也可能是续费成功收据）结果建议也让后台记录，可以查询出所有支付失败、成功的日志
            NSLog(@"IAP: 无订单的支付失败");
            NSDictionary *notifiUserInfo = @{@"error":@(0),
                                             @"result":@"支付中"};
            [NSNotificationCenter.defaultCenter postNotificationName:ZYPurchaseTransactionStatusChanged_Notifi object:nil userInfo:notifiUserInfo];
        }
        
        complete();
        return;
    }
    BOOL isRestored = (transaction.transactionState == SKPaymentTransactionStateRestored);
    BOOL isPurchased = (transaction.transactionState == SKPaymentTransactionStatePurchased);
    
    // 支付成功或续费成功的
    if (isRestored || isPurchased){
        NSString *logString = [NSString stringWithFormat:@"支付成功， 准备校验收据 t_id: %@, origin_t_id: %@", transaction.transactionIdentifier, transaction.originalTransaction.transactionIdentifier];
        self.logRecord(logString);
        
        ZYPurchaseTransactionModel *tModel = [self transactionModelFromSKTransaction:transaction];
        if (tModel) {
            // 处理能找到本地交易模型的交易
            [self handlerTransTransactions:transaction transactionModel:tModel complete:complete];
        } else {
            // 处理未找到本地交易模型的交易（若是续费成功的，则 originModel 可能会不为空，此时校验接口，可上行原始订单信息）
            [self handlerUnTransTransactions:transaction complete:complete];
        }
    }
}



- (void)handlerTransTransactions:(SKPaymentTransaction *)transaction // Apple 返回的交易
                transactionModel:(ZYPurchaseTransactionModel *)tModel  // 数据库查到的交易
                        complete:(dispatch_block_t)complete{
    // 能找到订单的交易
    __weak typeof(self) weakSelf = self;
    // 第一步：找收据
    [self requestReceiptInfo:transaction complete:^(BOOL success, id info) {
        NSString *logString = [NSString stringWithFormat:@"有订单收据请求结束 t_id: %@, origin_t_id: %@", transaction.transactionIdentifier, transaction.originalTransaction.transactionIdentifier];
        self.logRecord(logString);
        self.logRecord([NSString stringWithFormat:@"收据请求结果: %@", success?@"成功":@"失败"]);
        
        __strong typeof(weakSelf) strongSelf = weakSelf;
        if (success && info) {
            NSData *receipt = info;
            NSString *receiptStr = [receipt base64EncodedStringWithOptions:0];
            
            NSString *saveFileName = [ZYPurchaseTransactionModel generateReceiptDataFileName];
            if (receiptStr.zy_isValuable) {
                NSString *saveFilePath = [ZYPurchaseTransactionModel receiptDataFilePathForFileName:saveFileName];
                BOOL result = [ZYPurchaseTransactionModel saveReceiptData:receiptStr at:saveFilePath];
                if (result) {
                    tModel.receipt_data_filename = saveFileName;
                } else {
                    tModel.receipt_data_filename = nil;
                }
                self.logRecord([NSString stringWithFormat:@"存储了收据：%@", saveFileName]);
            }
            // 回调校验中状态
            tModel.transactionStatus = ZYPurchaseTransactionStatus_Verifing;
            [strongSelf.database updateTransactionModelStatus:tModel];
            [self responseTransactionStatusChangedInMainThread:tModel];
            NSDictionary *notifiUserInfo = @{@"error":@(0),
                                             @"status":@(tModel.transactionStatus),
                                             @"orderId":tModel.orderId,
                                             @"result":@"收据校验中"};
            [NSNotificationCenter.defaultCenter postNotificationName:ZYPurchaseTransactionStatusChanged_Notifi object:nil userInfo:notifiUserInfo];
            if (tModel.receipt_data_filename) {
                NSString *orderIdStr = tModel.orderId.zy_isValuable?tModel.orderId:@"";
                [strongSelf.database storageUnVerifyReceipt:tModel.receipt_data_filename orderId:tModel.orderId];
            }
            [strongSelf verifyReceipt:tModel.receipt_data_filename
                         transactions:transaction
                     transactionModel:tModel
                             complete:complete];
        } else {
            tModel.transactionStatus = ZYPurchaseTransactionStatus_Fail;
            [strongSelf.database updateTransactionModelStatus:tModel];
            [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
            [self responseTransactionStatusChangedInMainThread:tModel];
            NSDictionary *notifiUserInfo = @{@"error":@(70050),
                                             @"status":@(tModel.transactionStatus),
                                             @"orderId":tModel.orderId,
                                             @"result":@"订单无收据"};
            [NSNotificationCenter.defaultCenter postNotificationName:ZYPurchaseTransactionStatusChanged_Notifi object:nil userInfo:notifiUserInfo];
            complete();
        }
    }];
}

// MARK: 未找到本地交易记录的交易
- (void)handlerUnTransTransactions:(SKPaymentTransaction *)transaction // Apple 返回的交易
                          complete:(dispatch_block_t)complete{
    // 无主交易（也可能是续费成功收据）结果建议也让后台记录，可以查询出所有支付失败、成功的日志
    __weak typeof(self) weakSelf = self;
    // 第一步：找收据
    [self requestReceiptInfo:transaction complete:^(BOOL success, id info) {
        NSString *logString = [NSString stringWithFormat:@"没订单收据请求结束 t_id: %@, origin_t_id: %@", transaction.transactionIdentifier, transaction.originalTransaction.transactionIdentifier];
        self.logRecord(logString);
        self.logRecord([NSString stringWithFormat:@"收据请求结果: %@", success?@"成功":@"失败"]);
            
        NSDictionary *tpDict = @{@"state":@"1"};
        [NSNotificationCenter.defaultCenter postNotificationName:ZYPurchasePurchasedWithoutTransaction_Notifi object:nil userInfo:tpDict];
        __strong typeof(weakSelf) strongSelf = weakSelf;
        if (success && info) {
            NSData *receipt = info;
            NSString *receiptStr = [receipt base64EncodedStringWithOptions:0];
            NSString *deviceId = self.deviceUUID.zy_isValuable?self.deviceUUID:@"";
            NSMutableDictionary *requestDict = @{@"receipt_data": receiptStr,
                                                 @"deviceId":deviceId}.mutableCopy;
            
            if (ZYPurchaseSaleman.defaultSaleman.customerId.zy_isValuable) {
                requestDict[@"userid"] = ZYPurchaseSaleman.defaultSaleman.customerId;
            }
            if (ZYPurchaseSaleman.defaultSaleman.customerToken.zy_isValuable) {
                requestDict[@"user_token"] = ZYPurchaseSaleman.defaultSaleman.customerToken;
            }
            NSString *saveFileName = [ZYPurchaseTransactionModel generateReceiptDataFileName];
            if (receiptStr.zy_isValuable) {
                NSString *saveFilePath = [ZYPurchaseTransactionModel receiptDataFilePathForFileName:saveFileName];
                BOOL result = [ZYPurchaseTransactionModel saveReceiptData:receiptStr at:saveFilePath];
                if (!result) {
                    saveFileName = nil;
                }
            }
            self.logRecord([NSString stringWithFormat:@"存储了收据：%@", saveFileName]);
            if (transaction.transactionIdentifier.zy_isValuable) {
                requestDict[@"transcation_id"] = transaction.transactionIdentifier;
            }
            if (transaction.originalTransaction) {
                if (transaction.originalTransaction.transactionIdentifier.zy_isValuable) {
                    requestDict[@"origin_transcation_id"] = transaction.originalTransaction.transactionIdentifier;
                }
            }
            __block NSString *url = ZYPurchaseSaleman.formatPurchageUrlString(ZYPurchaseAPI_VerifyReceipt);
            // 第二步：提交收据
            [PJNetworkStation POST:url params:requestDict result:^(BOOL success, id info) {
                NSLog(@"IAP: 无主收据校验： %@, info:%@", success?@"成功":@"失败", info);
                self.logRecord([NSString stringWithFormat:@"没订单收据校验结果: %@", success?@"成功":@"失败"]);
                self.logRecord(info);
                
                if (success && [info isKindOfClass:[NSDictionary class]]) {
                    NSDictionary *dataDict = info;
                    NSDictionary *resultDict = @{};
                    if ([dataDict.allKeys containsObject:@"result"]) {
                        id resultObj = dataDict[@"result"];
                        if ([resultObj isKindOfClass:[NSDictionary class]]) {
                            resultDict = resultObj;
                        }
                    }
                    BOOL isNewGrant = NO;
                    if ([resultDict.allKeys containsObject:@"has_new_grant"]) {
                        id newGrantObj = resultDict[@"has_new_grant"];
                        if ([newGrantObj isKindOfClass:[NSString class]]) {
                            isNewGrant = [(((NSString *)newGrantObj).lowercaseString) isEqualToString:@"true"];
                        } else {
                            isNewGrant = [newGrantObj boolValue];
                        }
                    }
                    NSDictionary *tpDict = @{@"state":@"2", @"isNewGrant":@(isNewGrant)};
                    [NSNotificationCenter.defaultCenter postNotificationName:ZYPurchasePurchasedWithoutTransaction_Notifi object:nil userInfo:tpDict];
                    
                    NSString *orderSN = [resultDict zy_stringForKey:@"orderSN"];
                    ZYPurchaseTransactionModel *originModel = nil;
                    if (orderSN.zy_isValuable) {
                        originModel = [strongSelf.database queryTransactionModel:orderSN];
                        
                        NSString *orderIdInKeychain =  [ZYPurchaseDataBase lastIAPApplicationUsernameInKeychain];
                        if (orderIdInKeychain && orderSN.zy_isValuable && [orderIdInKeychain containsString:orderSN]) {
                            [ZYPurchaseDataBase clearLastIAPApplicationUsernameInKeychain];
                        }
                    }
                    if (originModel) {
                        if (saveFileName.zy_isValuable) {
                            originModel.receipt_data_filename = saveFileName;
                        }
                        
                        // 回调校验中状态
                        originModel.transactionStatus = ZYPurchaseTransactionStatus_Success;
                        if (transaction.transactionState == SKPaymentTransactionStateRestored) {
                            originModel.transactionStatus = ZYPurchaseTransactionStatus_Restored;
                        }
                        [strongSelf.database updateTransactionModelStatus:originModel];
                        
                        // 自动续期商品扣款成功的回调
                        NSLog(@"IAP: 扣款成功的订单收据，交易id： %@, 状态：%ld", originModel.orderId, (long)originModel.transactionStatus);
                        NSDictionary *notifiUserInfo = @{@"error":@(0),
                                                         @"orderId":orderSN,
                                                         @"isNewGrant":@(isNewGrant),
                                                         @"result":@"续费成功订单有收据"};
                        [NSNotificationCenter.defaultCenter postNotificationName:ZYPurchaseTransactionStatusChanged_Notifi object:nil userInfo:notifiUserInfo];
                        
                    } else {
                        // 无主交易有收据
                        NSLog(@"IAP: 无主的订单收据，交易id： %@, 状态：%ld", transaction.transactionIdentifier, (long)transaction.transactionState);
                        NSDictionary *notifiUserInfo = @{@"error":@(0),
                                                         @"isNewGrant":@(isNewGrant),
                                                         @"result":@"无主订单且有收据"};
                        [NSNotificationCenter.defaultCenter postNotificationName:ZYPurchaseTransactionStatusChanged_Notifi object:nil userInfo:notifiUserInfo];
                    }
                    
                } else {
                    NSDictionary *tpDict = @{@"state":@"3"};
                    [NSNotificationCenter.defaultCenter postNotificationName:ZYPurchasePurchasedWithoutTransaction_Notifi object:nil userInfo:tpDict];
                    BOOL isNetworkErr = NO;
                    BOOL serverLost = NO;       // 服务器自身原因未校验
                    BOOL haveBind = NO;       // 是否有绑定过其他账号
                    NSInteger errorCodeValue = 0;
                    if (info && [info isKindOfClass:[NSDictionary class]]) {
                        NSDictionary *dataDict = info;
                        if ([dataDict.allKeys containsObject:@"errcode"]) {
                            NSInteger errorCodeValue = [dataDict[@"errcode"] integerValue];
                            if (errorCodeValue == -9999) {
                                isNetworkErr = YES;
                            }
                            if (self.shouldReVerifyReceiptByServerLost(errorCodeValue)) {
                                serverLost = YES;
                            }
                            if (errorCodeValue == 20034) {
                                haveBind = YES;
                            }
                        }
                    }
                    if ((isNetworkErr || serverLost) && saveFileName.zy_isValuable) {
                        // 没发到后台的收据找时间再次提交
                        [self.database storageUnVerifyReceipt:saveFileName orderId:@""];
                    } else {
                        [self.database reVerifyReceiptsSuccess:saveFileName];
                    }
                }
                complete();
            }];
        } else {
            NSLog(@"IAP: 无主交易且无收据，交易id： %@ 状态: %ld", transaction.transactionIdentifier, (long)transaction.transactionState);
            NSDictionary *notifiUserInfo = @{@"error":@(70050), @"result":@"订单无收据"};
            [NSNotificationCenter.defaultCenter postNotificationName:ZYPurchaseTransactionStatusChanged_Notifi object:nil userInfo:notifiUserInfo];
            complete();
        }
        [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
    }];
}

// MARK: 异步获取收据（若本地存在则直接返回）
- (void)requestReceiptInfo:(SKPaymentTransaction *)transaction complete:(void(^)(BOOL success, id info))complete{
    if (!complete) {
        return;
    }
    if (!transaction.transactionIdentifier || (transaction.transactionIdentifier.length == 0)) {
        complete(NO, @"交易信息异常");
    }
    /**
     三步查找
     1. appStoreReceiptURL 中找
     2. 数据库中找
     3. SKReceiptRefreshRequest 请求
     */
    NSURL *receiptURL = [[NSBundle mainBundle] appStoreReceiptURL];
    if([[NSFileManager defaultManager] fileExistsAtPath:receiptURL.path]) {
        NSData *receipt = [NSData dataWithContentsOfURL:receiptURL];
        complete(YES, receipt);
    } else {
        NSString *transactionId;
        if (transaction.originalTransaction) {
            transactionId = transaction.originalTransaction.transactionIdentifier;
        } else {
            transactionId = transaction.transactionIdentifier;
        }
        ZYPurchaseTransactionModel *tModel = [self.database queryTransactionModelByTransactionId:transactionId];
        NSString *receiptInfo = nil;
        if (tModel) {
            receiptInfo = tModel.receiptDataLocal;
        }
        if (receiptInfo) {
            complete(YES, receiptInfo);
        } else {
            self.requestReceiptBlock = nil;
            self.requestReceiptBlock = complete;
            
            SKReceiptRefreshRequest *receiptRefreshRequest = [[SKReceiptRefreshRequest alloc] initWithReceiptProperties:nil];
            receiptRefreshRequest.delegate = self;
            [receiptRefreshRequest start];
            self.receiptRequest = receiptRefreshRequest;
        }
    }
}

/// 定位本地数据库id
- (ZYPurchaseTransactionModel *)transactionModelFromSKTransaction:(SKPaymentTransaction *)transaction{
    /**
    三层逻辑寻找 applicationUsername，上层找到则停止不再继续 applicationUsername（主要用到订单id），没有订单号则无法定位收据归属，但依然调用接口传给服务器，此单已丢失，服务器去存储无主收据，方便用户后期申诉
    1. 从 Apple 返回的支付模型中取;
    2. 从当前进行中的交易中（saleman同一时间只会处理一个交易）；
    3. 从钥匙串中取
    */
    NSString *targetOrderId = nil;
    if (transaction.payment.applicationUsername.zy_isValuable) {
        targetOrderId = [ZYPurchaseTransactionModel fetchOrderIdFromApplicationUsername:transaction.payment.applicationUsername];
        if (targetOrderId.zy_isValuable) {
            self.logRecord(@"从 applicationUsername 找到了orderId");
        }
    }
    if (!targetOrderId) {
        targetOrderId = self.currentTransaction.orderId;
        if (targetOrderId.zy_isValuable) {
            self.logRecord(@"从 当前校验模型 找到了orderId");
        }
    }
    if (!targetOrderId) {
        targetOrderId = [ZYPurchaseDataBase lastIAPApplicationUsernameInKeychain];
        if (targetOrderId.zy_isValuable) {
            self.logRecord(@"从 钥匙串中 找到了orderId");
        }
    }
    if (!targetOrderId.zy_isValuable) {
        self.logRecord(@"没找到 orderId");
    }
    ZYPurchaseTransactionModel *retModel = nil;
    if (targetOrderId) {
        retModel = [self.database queryTransactionModel:targetOrderId];
        retModel.transactionId = transaction.transactionIdentifier;
        if (transaction.originalTransaction) {
            retModel.transactionId_origin = transaction.originalTransaction.transactionIdentifier;
        }
    }
    if (!retModel) {
        if (transaction.originalTransaction && transaction.originalTransaction.transactionIdentifier) {
            ZYPurchaseTransactionModel *retModel = [self.database queryTransactionModelByTransactionId:transaction.originalTransaction.transactionIdentifier];
            self.logRecord(@"从 原始交易id 找到了交易");
            return retModel;
        }
    }
    return retModel;
}

// MARK: - 查询商品价格
+ (void)queryPrice:(nonnull NSArray *)productsArray complete:(nullable void (^)(BOOL success, id info))complete{
    [[ZYPurchaseSaleman defaultSaleman] queryPrice:productsArray complete:complete invalidProductIdentifiers:nil];
}

+(void)queryPrice:(NSArray *)productsArray complete:(void (^)(BOOL, id _Nonnull))complete invalidProductIdentifiers:(void (^)(id _Nonnull))invalidProductIdentifiers{
    [[ZYPurchaseSaleman defaultSaleman] queryPrice:productsArray complete:complete invalidProductIdentifiers:invalidProductIdentifiers];

}
- (void)queryPrice:(nonnull NSArray *)productsArray complete:(nullable void (^)(BOOL success, id info))complete invalidProductIdentifiers:(void (^)(id _Nonnull))invalidProductIdentifiers{
    if (!productsArray ||
        ![productsArray isKindOfClass:[NSArray class]] ||
        (productsArray.count == 0)) {
        if (complete) {
            complete(NO, @"Products empty");
        }
        return;
    }
    BOOL needRequest = YES;
//    if (self.priceRequest &&
//        self.priceRequest.productsInfo &&
//        (self.priceRequest.productsInfo.count == productsArray.count) &&
//        self.priceRequest.productsIdArray &&
//        (self.priceRequest.productsIdArray.count == productsArray.count)) {
//        BOOL isEqual = YES;
//        for (NSInteger idx = 0; idx < productsArray.count; idx++) {
//            NSString *idStr = productsArray[idx];
//            NSString *idStrCached = self.priceRequest.productsIdArray[idx];
//            if (![idStr isEqualToString:idStrCached]) {
//                isEqual = NO;
//            }
//        }
//        if (isEqual) {
//            needRequest = NO;
//        }
//    }
    if (needRequest) {
        ZYProductsRequest *request = [[ZYProductsRequest alloc] initWithProductIdentifiers:[NSSet setWithArray:productsArray]];
        request.isPriceRequest = YES;
        request.productsIdArray = productsArray;
        request.delegate = self;
        [request start];
        self.priceRequest = request;
        self.priceRequestHandler = complete;
        self.invalidProductIdentifiers = invalidProductIdentifiers;
        NSLog(@"IAP: 没缓存过商品列表，开始请求");
        self.logRecord(@"IAP: 没缓存过商品列表，开始请求");
    } else {
        NSMutableArray *retArr = @[].mutableCopy;
        for (NSInteger idx = 0; idx < self.priceRequest.productsInfo.count; idx++) {
            NSDictionary *proDict = self.priceRequest.productsInfo[idx];
            if (proDict) {
                NSMutableDictionary *proDictM = @{}.mutableCopy;
                proDictM[@"third_product_id"] = [proDict zy_stringForKey:@"third_product_id"];
                proDictM[@"price"] = [proDict objectForKey:@"price"];
                proDictM[@"currency_symbol"] = [proDict zy_stringForKey:@"currencySymbol"];
                [retArr addObject:proDictM];
            }
        }
        if (complete) {
            complete(YES, retArr);
        }
        NSLog(@"IAP: 缓存过商品列表，不需要再次请求");
        self.logRecord(@"IAP: 缓存过商品列表，不需要再次请求");
    }
}

+ (NSString *)replaceUnicode:(NSString *)unicodeStr
{
    NSString *tempStr1 = [unicodeStr stringByReplacingOccurrencesOfString:@"\\u"withString:@"\\U"];
    NSString *tempStr2 = [tempStr1 stringByReplacingOccurrencesOfString:@"\""withString:@"\\\""];
    NSString *tempStr3 = [[@"\""stringByAppendingString:tempStr2] stringByAppendingString:@"\""];
    NSData *tempData = [tempStr3 dataUsingEncoding:NSUTF8StringEncoding];
    NSString* returnStr = [NSPropertyListSerialization propertyListFromData:tempData
                                                           mutabilityOption:NSPropertyListImmutable
                                                                     format:NULL
                                                           errorDescription:NULL];
    return [returnStr stringByReplacingOccurrencesOfString:@"\\r\\n"withString:@"\n"];
}

// MARK: SKProductsRequestDelegate - 收到产品返回信息
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response{
    if ([request isKindOfClass:[ZYProductsRequest class]]) {
        ZYProductsRequest *priceRequest = (ZYProductsRequest *)request;
        if (priceRequest.isPriceRequest) {
            NSArray <SKProduct *>*products = response.products;
            NSArray *productsInvalid = response.invalidProductIdentifiers;
            if(productsInvalid.count > 0){
                if(self.invalidProductIdentifiers){
                    self.invalidProductIdentifiers(productsInvalid);
                }
            }
            if (priceRequest.productsIdArray && self.priceRequestHandler) {
                NSMutableArray *proArray = @[].mutableCopy;
                NSMutableArray *retArray = @[].mutableCopy;
                for (NSInteger idx = 0; idx < priceRequest.productsIdArray.count; idx++) {
                    NSString *proId = priceRequest.productsIdArray[idx];
                    for (SKProduct *product in products) {
                        if ([product.productIdentifier isEqualToString:proId]) {
                            NSMutableDictionary *proDict = @{}.mutableCopy;
                            proDict[@"third_product_id"] = product.productIdentifier;
                            proDict[@"price"] = @(product.price.doubleValue);
                            proDict[@"currency_symbol"] = [ZYPurchaseSaleman replaceUnicode:product.priceLocale.currencySymbol];
                            [retArray addObject:proDict];
                            
                            NSMutableDictionary *proDict1 = @{}.mutableCopy;
                            if (product.priceLocale.currencySymbol) {
                                proDict1[@"currencySymbol"] = product.priceLocale.currencySymbol;
                            }
                            if (product.priceLocale.currencyCode) {
                                proDict1[@"currencyCode"] = product.priceLocale.currencyCode;
                            }
                            proDict1[@"price"] = @(product.price.doubleValue);
                            proDict1[@"third_product_id"] = product.productIdentifier;
                            [proArray addObject:proDict1];
                            break;
                        }
                    }
                }
                self.priceRequest.productsInfo = proArray;
                self.priceRequestHandler(YES, retArray);
            } else {
                self.priceRequestHandler(NO, @"Product empty");
            }
        } else {
            if ([response.invalidProductIdentifiers containsObject:ZYPurchase_CountryCodeRequest_ProductId]) {
                NSLog(@"IAP: 国家码请求结束: %@", self.countryCode);
                if (self.countryCodeRequestBlock) {
                    self.countryCodeRequestBlock(self.countryCode);
                    self.countryCodeRequestBlock = nil;
                }
                return;
            }
            ZYProductsRequest *coutrycodeRequest = (ZYProductsRequest *)request;
            NSArray <SKProduct *>*products = response.products;
            if (products && (products.count > 0)) {
                NSLocale *priceLocale = products.firstObject.priceLocale;
                self.countryCode = priceLocale.countryCode;
                NSString *jsonPath = [[NSBundle mainBundle] pathForResource:@"CountryCode" ofType:@"json"];
                NSData *jsonData = [[NSData alloc] initWithContentsOfFile:jsonPath];
                NSError *error;
                id jsonObj = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:&error];
                if (jsonObj && [jsonObj isKindOfClass:[NSDictionary class]] && self.countryCode.zy_isValuable) {
                    NSDictionary *countryDict = jsonObj;
                    if ([countryDict.allKeys containsObject:self.countryCode]) {
                        NSDictionary *countryInfo = countryDict[self.countryCode];
                        self.countryCode = countryInfo[@"code_alpha-3"];
                    }
                }
                NSLog(@"IAP: 国家码请求结束: %@", self.countryCode);
                if (self.countryCodeRequestBlock) {
                    self.countryCodeRequestBlock(self.countryCode);
                    self.countryCodeRequestBlock = nil;
                }
            }
        }
        return;
    }
    if (!self.products || (self.products.count == 0) || !self.customerId.zy_isValuable) {
        [self responseCreateOrderFailureInMainthread:ZYPurchaseSaleman.formatErrorResponse(70001)];
        [NSNotificationCenter.defaultCenter postNotificationName:ZYPurchaseCreateOrderComplete_Notifi object:nil userInfo:@{@"error":@(70001)}];
        return;
    }
    if (!response || !response.products) {
        self.logRecord([NSString stringWithFormat:@"未从 Apple 查询到商品---"]);
        [self responseCreateOrderFailureInMainthread:ZYPurchaseSaleman.formatErrorResponse(70005)];
        NSMutableDictionary *mDict = @{@"error":@(70005)};
        if (self.products) {
            mDict[@"product"] = self.products;
        }
        dispatch_async(dispatch_get_main_queue(), ^{
            if (self.createOrderBlock) {
                self.createOrderBlock(NO, mDict);
                self.createOrderBlock = nil;
                [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(createOrderUnknownTimeout) object:nil];
            }
        });
        [NSNotificationCenter.defaultCenter postNotificationName:ZYPurchaseCreateOrderComplete_Notifi object:nil userInfo:mDict];
        return;
    }
    NSArray *product = response.products;
    NSDictionary *productDict = self.products.firstObject;
    NSString *productIdentifier = [productDict zy_stringForKey:@"productIdentifier"];
    if (((response.invalidProductIdentifiers.count > 0) && ([response.invalidProductIdentifiers containsObject:productIdentifier])) ||
        (product.count==0)) {
        self.logRecord([NSString stringWithFormat:@"未从 Apple 查询到商品: %@", productIdentifier]);
        // 未找到商品
        [self responseCreateOrderFailureInMainthread:ZYPurchaseSaleman.formatErrorResponse(70005)];
        dispatch_async(dispatch_get_main_queue(), ^{
            if (self.createOrderBlock) {
                self.createOrderBlock(NO, @{@"product":self.products, @"error":@(70005)});
                self.createOrderBlock = nil;
                [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(createOrderUnknownTimeout) object:nil];
            }
        });
        [NSNotificationCenter.defaultCenter postNotificationName:ZYPurchaseCreateOrderComplete_Notifi object:nil userInfo:@{@"product":self.products, @"error":@(70005)}];
        return;
    }
    
    SKProduct *targetProduct = nil;
    if (product.count > 0) {
        for (NSInteger idx = 0; idx < product.count; idx++) {
            SKProduct *pro = product[idx];
            NSString *locTitle = [pro localizedTitle];
            NSString *locDes = [pro localizedDescription];
            id price = [pro price];
            NSString *proIden = [pro productIdentifier];
            locTitle = locTitle.zy_isValuable?locTitle:@"";
            locDes = locDes.zy_isValuable?locDes:@"";
            if (locTitle && locDes && price && proIden) {
                NSDictionary *productInfo = @{@"localizedTitle":locTitle,
                                              @"localizedDescription":locDes,
                                              @"price":[pro price],
                                              @"productIdentifier":[pro productIdentifier]};
                NSLog(@"IAP: 找到产品信息  == %@", productInfo);
                if([pro.productIdentifier isEqualToString:productIdentifier]){
                    targetProduct = pro;
                    break;
                }
            }
        }
    }
    
    if (!targetProduct) {
        self.logRecord([NSString stringWithFormat:@"未从 Apple 查询到商品: %@", productIdentifier]);
        // 未找到商品
        [self responseCreateOrderFailureInMainthread:ZYPurchaseSaleman.formatErrorResponse(70004)];
        dispatch_async(dispatch_get_main_queue(), ^{
            if (self.createOrderBlock) {
                self.createOrderBlock(NO, @{@"product":self.products, @"error":@(70004)});
                self.createOrderBlock = nil;
                [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(createOrderUnknownTimeout) object:nil];
            }
        });
        [NSNotificationCenter.defaultCenter postNotificationName:ZYPurchaseCreateOrderComplete_Notifi object:nil userInfo:@{@"product":self.products, @"error":@(70004)}];
        return;
    }
    self.logRecord([NSString stringWithFormat:@"已找到商品: %@，开始创建订单", productIdentifier]);
    [ZYPurchaseSaleman createOrder:self.products
                         isDigital:YES
                          complete:^(BOOL success, id  _Nonnull info) {
        
        if (success && [info isKindOfClass:[ZYPurchaseOrderModel class]]) {
            ZYPurchaseOrderModel *orderModel = info;
            dispatch_async(dispatch_get_main_queue(), ^{
                if (self.createOrderBlock) {
                    NSString *logString = [NSString stringWithFormat:@"IAP: 返回订单号：%@", orderModel.orderId];
                    NSLog(logString);
                    self.createOrderBlock(YES, orderModel.orderId);
                    self.createOrderBlock = nil;
                    self.logRecord(logString);
                    [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(createOrderUnknownTimeout) object:nil];
                }
            });
            [NSNotificationCenter.defaultCenter postNotificationName:ZYPurchaseCreateOrderComplete_Notifi object:nil userInfo:@{@"order":orderModel.orderId?orderModel.orderId:@"", @"error":@(0)}];
            dispatch_async(dispatch_get_main_queue(), ^{
                // 开始创建订单并发起购买
                [self startIAPPay:targetProduct order:orderModel];
                if (self.order_delegate && [self.order_delegate respondsToSelector:@selector(createOrderSuccess:)]) {
                    [self.order_delegate createOrderSuccess:orderModel];
                }
            });
        } else {
            // 创建订单失败
            [self responseCreateOrderFailureInMainthread:ZYPurchaseSaleman.formatErrorResponse(70003)];
            dispatch_async(dispatch_get_main_queue(), ^{
                if (self.createOrderBlock) {
                    self.createOrderBlock(NO, info);
                    self.createOrderBlock = nil;
                    [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(createOrderUnknownTimeout) object:nil];
                }
            });
            [NSNotificationCenter.defaultCenter postNotificationName:ZYPurchaseCreateOrderComplete_Notifi object:nil userInfo:@{@"product":self.products, @"error":@(70003)}];
        }
    }];
}

// 发起IAP支付
- (void)startIAPPay:(SKProduct *)targetProduct order:(ZYPurchaseOrderModel *)order{
    order.IAPProduct = targetProduct;
    
    self.currentTransaction = [ZYPurchaseTransactionModel formatIAPTransaction:order];
    [self.currentTransaction startPayment];
    self.currentTransaction = [self.database insertTransactionModel:self.currentTransaction];
    NSLog(@"IAP: 开始支付了: %@", self.currentTransaction?@"插入成功":@"插入失败");
    self.logRecord([NSString stringWithFormat:@"开始支付：%@", order.orderId]);
    [self responseTransactionStatusChangedInMainThread:self.currentTransaction];
}

- (void)responseTransactionStatusChangedInMainThread:(ZYPurchaseTransactionModel *)transaction{
    dispatch_async(dispatch_get_main_queue(), ^{
        if (self.transaction_delegate && [self.transaction_delegate respondsToSelector:@selector(transactionStatusChanged:)]) {
            [self.transaction_delegate transactionStatusChanged:transaction];
        }
    });
}

// MARK: SKRequestDelegate - 请求失败
- (void)request:(SKRequest *)request didFailWithError:(NSError *)error{
    NSLog(@"IAP: SKRequestDelegate > didFailWithError: %@", error);
    self.logRecord([NSString stringWithFormat:@"Apple 请求失败了: %@", error.description]);
    if (self.receiptRequest == request) {
        if (self.requestReceiptBlock) {
            self.requestReceiptBlock(NO, error.description);
        }
    }
    if ([request isKindOfClass:[SKProductsRequest class]] && ![request isKindOfClass:[ZYProductsRequest class]]) {
        dispatch_async(dispatch_get_main_queue(), ^{
            if (self.createOrderBlock) {
                self.createOrderBlock(NO, ZYPurchaseSaleman.formatErrorResponse(70101));
                self.createOrderBlock = nil;
                [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(createOrderUnknownTimeout) object:nil];
            }
        });
    }
}
// 请求结束
- (void)requestDidFinish:(SKRequest *)request{
    NSLog(@"IAP: SKRequestDelegate > requestDidFinish");
    if (self.receiptRequest == request) {
        if (self.requestReceiptBlock) {
            NSURL *receiptURL = [[NSBundle mainBundle] appStoreReceiptURL];
            BOOL success = [[NSFileManager defaultManager] fileExistsAtPath:receiptURL.path];
            if (success) {
                NSData *receipt = [NSData dataWithContentsOfURL:receiptURL];
                self.requestReceiptBlock(YES, receipt);
            } else {
                self.requestReceiptBlock(NO, @"找不到收据文件");
            }
        }
    }
}

static BOOL startIAPPaymentEnable = YES;
#pragma mark - IAP
- (BOOL)startIAPPayment:(nonnull NSDictionary *)productDict
               complete:(nullable void (^)(BOOL success, id info))complete{
    if (!startIAPPaymentEnable) {
        if (complete) {
            complete(NO, @{@"errmsg":@"Relax please!", @"errcode":@"70100"});
        }
        return NO;
    }
    startIAPPaymentEnable = NO;
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0f * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        startIAPPaymentEnable = YES;
    });
    NSLog(@"IAP: 开始购买商品：%@", productDict);
    self.logRecord([NSString stringWithFormat:@"开始购买商品"]);
    self.logRecord(productDict);
    if (!AFNetworkReachabilityManager.sharedManager.isReachable) {
        NSLog(@"IAP: 网络未连接, 已停止");
        if (complete) {
            complete(NO, ZYPurchaseSaleman.formatErrorResponse(70101));
        }
        return NO;
    }
    if (!self.customerId.zy_isValuable ||
        !self.customerToken.zy_isValuable) {
        NSLog(@"IAP: 用户信息不全, 已停止");
        if (complete) {
            complete(NO, @{@"errmsg":@"Need user info!", @"errcode":@"70001"});
        }
        return NO;
    }
    // 检测是否支持内购
    if (![ZYPurchaseSaleman supportPaymentMethod:ZYPurchasePaymentMethod_IAP]) {
        NSLog(@"IAP: 当前用户不支持内购, 已停止");
        if (complete) {
            complete(NO, ZYPurchaseSaleman.formatErrorResponse(70007));
        }
        return NO;
    }
    if ([self shouldReVerifyReceiptOrder]) {
        // 存在未完成的交易
        [self responseCreateOrderFailureInMainthread:ZYPurchaseSaleman.formatErrorResponse(70099)];
        NSMutableDictionary *userInfo = @{@"error":@(70099)}.mutableCopy;
        if (self.products) {
            userInfo[@"product"] = self.products;
        }
        [NSNotificationCenter.defaultCenter postNotificationName:ZYPurchaseCreateOrderComplete_Notifi object:nil userInfo:userInfo];
        NSLog(@"IAP: 存在未完成的交易, 已停止");
        if (complete) {
            complete(NO, ZYPurchaseSaleman.formatErrorResponse(70099));
        }
        return NO;
    }
    self.createOrderBlock = complete;
    
    [self performSelector:@selector(createOrderUnknownTimeout) withObject:nil afterDelay:60.0f];
    
    self.products = @[productDict];
    NSString *productIdentifier = [productDict zy_stringForKey:@"productIdentifier"];
    
    self.logRecord([NSString stringWithFormat:@"开始查询商品: %@", productIdentifier]);
    SKProductsRequest *request = [[SKProductsRequest alloc] initWithProductIdentifiers:[NSSet setWithObject:productIdentifier]];
    request.delegate = self;
    [request start];
    return YES;
}
- (BOOL)startIAPPayment:(nonnull NSDictionary *)productDict{
    return [self startIAPPayment:productDict complete:nil];
}
- (void)createOrderUnknownTimeout{
    dispatch_async(dispatch_get_main_queue(), ^{
        if (self.createOrderBlock) {
            self.createOrderBlock(NO, ZYPurchaseSaleman.formatErrorResponse(70102));
            self.createOrderBlock = nil;
        }
    });
}

- (void)responseCreateOrderFailureInMainthread:(id)error{
    dispatch_async(dispatch_get_main_queue(), ^{
        if (self.order_delegate && [self.order_delegate respondsToSelector:@selector(createOrderFailWithError:)]) {
            [self.order_delegate createOrderFailWithError:error];
        }
    });
}
+ (NSString *)needReVerifyOrderId{
    return [[ZYPurchaseSaleman defaultSaleman] needReVerifyOrderId];
}
- (NSString *)needReVerifyOrderId{
    NSArray <ZYPurchaseTransactionModel *>*needVerifyArr = [self.database queryAllTransactionModelsUnVerifyReceipt];
    if (needVerifyArr && (needVerifyArr.count > 0)) {
        return needVerifyArr.firstObject.orderId;
    }
    return nil;
}
// 从支付队列中获取指定交易标识的交易模型
- (nullable SKPaymentTransaction *)fetchTransactionInSKQueue:(NSString *)transactionIdentifier{
    NSArray *transactions = [SKPaymentQueue defaultQueue].transactions;
    if (transactions.count == 0) {
        return nil;
    }
    SKPaymentTransaction *targetTransaction = nil;
    for (NSInteger idx = 0; idx < transactions.count; idx++) {
        SKPaymentTransaction *transaction = transactions[idx];
        if ([transaction.transactionIdentifier isEqualToString:transactionIdentifier]) {
            targetTransaction = transaction;
        }
    }
    return targetTransaction;
}
- (BOOL)shouldReVerifyReceiptOrderWithOrderId:(NSString *)orderId{
    if (!orderId.zy_isValuable) {
        return NO;
    }
    ZYPurchaseTransactionModel *transactionModel = [self.database queryTransactionModel:orderId];
    if (transactionModel) {
        NSString *receipt = transactionModel.receiptDataLocal;
        if (!receipt || !transactionModel.transactionId.zy_isValuable) {
            return NO;
        }
        SKPaymentTransaction *targetTransaction = [self fetchTransactionInSKQueue:transactionModel.transactionId];
        return targetTransaction?YES:NO;
    }
    return NO;
}
// 该订单是否未校验收据
- (BOOL)shouldReVerifyReceiptOrder{
    NSString *orderId = [self needReVerifyOrderId];
    return [self shouldReVerifyReceiptOrderWithOrderId:orderId];
}
// 再次校验收据
- (BOOL)reVerifyReceiptComplete:(void(^)(BOOL success, id info))complete{
    NSString *orderId = [self needReVerifyOrderId];
    BOOL shouldReVerify = [self shouldReVerifyReceiptOrderWithOrderId:orderId];
    if (!shouldReVerify) {
        if (complete) {
            complete(NO, @"Need not reverify receipt");
        }
        return NO;
    }
    ZYPurchaseTransactionModel *transactionModel = [self.database queryTransactionModel:orderId];
    SKPaymentTransaction *targetTransaction = [self fetchTransactionInSKQueue:transactionModel.transactionId];
    self.reVerifyOrderId = transactionModel.orderId;
    __weak typeof(self) weakSelf = self;
    [self verifyReceipt:transactionModel.receipt_data_filename
           transactions:targetTransaction
       transactionModel:transactionModel
               complete:^{
        __strong typeof(weakSelf) strongSelf = weakSelf;
        
        if (strongSelf.currentTransaction) {
            ZYPurchaseTransactionStatus curTransactionStatus = [strongSelf.database queryTransactionModelTransactionStatus:strongSelf.currentTransaction.orderId];
            if ((curTransactionStatus == ZYPurchaseTransactionStatus_Cancel) ||
                (curTransactionStatus == ZYPurchaseTransactionStatus_Fail) ||
                (curTransactionStatus == ZYPurchaseTransactionStatus_Success) ||
                (curTransactionStatus == ZYPurchaseTransactionStatus_ReceiptInvalid) ||
                (curTransactionStatus == ZYPurchaseTransactionStatus_RePurchase) ||
                (curTransactionStatus == ZYPurchaseTransactionStatus_Restored)) {
                strongSelf.currentTransaction = nil;
                NSLog(@"IAP: 释放了当前交易模型");
            } else {
                NSLog(@"IAP: reVerify 还不能释放了当前交易模型 订单：%@ 状态： %ld", strongSelf.currentTransaction.orderId, curTransactionStatus);
            }
        }
        ZYPurchaseTransactionModel *retModel = [strongSelf.database queryTransactionModel:orderId];
        if (retModel) {
            complete(YES, retModel);
        }
        strongSelf.reVerifyOrderId = nil;
    }];
    return YES;
}

#pragma mark - 校验收据
- (void)verifyReceipt:(NSString *)receiptFileName
         transactions:(SKPaymentTransaction *)transaction // Apple 返回的交易
     transactionModel:(ZYPurchaseTransactionModel *)tModel  // 数据库查到的交易
             complete:(dispatch_block_t)complete{
    NSString *receiptStr = [ZYPurchaseTransactionModel receiptStringWithName:receiptFileName];
    if (!receiptStr.zy_isValuable) {
        if (complete) {
            complete();
        }
        return;
    }
    NSString *customerId = ZYPurchaseSaleman.defaultSaleman.customerId ? ZYPurchaseSaleman.defaultSaleman.customerId : @"";
    NSString *customerToken = ZYPurchaseSaleman.defaultSaleman.customerToken ? ZYPurchaseSaleman.defaultSaleman.customerToken : @"";
    NSMutableDictionary *requestDict = @{@"receipt_data": receiptStr,
                                         @"userid":customerId,
                                         @"user_token":customerToken,
                                         @"orderSN":tModel.orderId,
                                         @"deviceId":ZYPurchaseSaleman.defaultSaleman.deviceUUID}.mutableCopy;
    if (transaction.transactionIdentifier.zy_isValuable) {
        requestDict[@"transcation_id"] = transaction.transactionIdentifier;
    }
    if (transaction.originalTransaction) {
        if (transaction.originalTransaction.transactionIdentifier.zy_isValuable) {
            requestDict[@"origin_transcation_id"] = transaction.originalTransaction.transactionIdentifier;
        }
    }
    NSString *transcation_id = [requestDict zy_stringForKey:@"transcation_id"];
    NSString *origin_transcation_id = [requestDict zy_stringForKey:@"origin_transcation_id"];
    NSLog(@"IAP: 校验收据params 交易id: %@, 原始交易id: %@", transcation_id, origin_transcation_id);
    NSString *url = ZYPurchaseSaleman.formatPurchageUrlString(ZYPurchaseAPI_VerifyReceipt);
    // 第二步：提交收据
    PJRequest *request = [PJRequest request:PJHttpMethodPOST
                                  urlString:url
                                     params:requestDict
                                     header:nil];
    request.timeoutInterval = 30.0f*3;
    [PJNetworkStation.shareStation startRequest:request result:^(BOOL success, id info) {
        NSLog(@"IAP: 收据校验params： 结果， %@ info：%@", success?@"成功":@"失败", info);
        
        self.logRecord([NSString stringWithFormat:@"收据校验结果：%@", success?@"成功":@"失败"]);
        self.logRecord(info);
        if (success) {
            // 正常结束交易
            tModel.transactionStatus = ZYPurchaseTransactionStatus_Success;
            if (transaction.transactionState == SKPaymentTransactionStateRestored) {
                tModel.transactionStatus = ZYPurchaseTransactionStatus_Restored;
            }
            [self.database updateTransactionModelStatus:tModel];
            [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
            BOOL isNewGrant = NO;
            NSString *orderSN;
            if (info && [info isKindOfClass:[NSDictionary class]]) {
                id resultObj = [info objectForKey:@"result"];
                if (resultObj && [resultObj isKindOfClass:[NSDictionary class]]) {
                    tModel.receiptResult = resultObj;
                    if ([tModel.receiptResult.allKeys containsObject:@"has_new_grant"]) {
                        id newGrantObj = tModel.receiptResult[@"has_new_grant"];
                        if ([newGrantObj isKindOfClass:[NSString class]]) {
                            isNewGrant = [(((NSString *)newGrantObj).lowercaseString) isEqualToString:@"true"];
                        } else {
                            isNewGrant = [newGrantObj boolValue];
                        }
                    }
                    orderSN = [tModel.receiptResult zy_stringForKey:@"orderSN"];
                }
            }
            BOOL isVerifingOrder = NO;
            if (orderSN.zy_isValuable && tModel.orderId.zy_isValuable) {
                isVerifingOrder = [tModel.orderId isEqualToString:orderSN];
            }
            if (isVerifingOrder) {
                if (isNewGrant) {
                    [self responseTransactionStatusChangedInMainThread:tModel];
                    NSDictionary *notifiUserInfo = @{@"error":@(0),
                                                     @"status":@(tModel.transactionStatus),
                                                     @"orderId":tModel.orderId,
                                                     @"isNewGrant":@(isNewGrant),
                                                     @"result":@"支付成功"};
                    [NSNotificationCenter.defaultCenter postNotificationName:ZYPurchaseTransactionStatusChanged_Notifi object:nil userInfo:notifiUserInfo];
                } else {
                    [self.database updateTransactionModelStatus:tModel];
                    [self responseTransactionStatusChangedInMainThread:tModel];
                    NSDictionary *notifiUserInfo = @{@"error":@(0),
                                                     @"status":@(tModel.transactionStatus),
                                                     @"orderId":tModel.orderId,
                                                     @"isNewGrant":@(isNewGrant),
                                                     @"result":@"重复购买"};
                    [NSNotificationCenter.defaultCenter postNotificationName:ZYPurchaseTransactionStatusChanged_Notifi object:nil userInfo:notifiUserInfo];
                }
            }
            NSLog(@"IAP: %ld-%ld 交易检测, orderSN: %@, tModel.orderId:%@,  currentTransaction: %@", isVerifingOrder, isNewGrant, orderSN, tModel.orderId, self.currentTransaction.orderId);
            if (tModel.receiptResult) {
                NSString *orderSN = [tModel.receiptResult zy_stringForKey:@"orderSN"];
                NSString *orderIdInKeychain =  [ZYPurchaseDataBase lastIAPApplicationUsernameInKeychain];
                if (orderIdInKeychain && orderSN && [orderIdInKeychain containsString:orderSN]) {
                    [ZYPurchaseDataBase clearLastIAPApplicationUsernameInKeychain];
                }
            }
        } else {
            BOOL isNetworkErr = NO;     // 网络原因未校验
            BOOL serverLost = NO;       // 服务器自身原因未校验
            BOOL haveBind = NO;       // 是否有绑定过其他账号
            NSInteger errorCodeValue = 0;
            if (info && [info isKindOfClass:[NSDictionary class]]) {
                NSDictionary *dataDict = info;
                if ([dataDict.allKeys containsObject:@"errcode"]) {
                    NSInteger errorCodeValue = [dataDict[@"errcode"] integerValue];
                    if (errorCodeValue == -9999) {
                        isNetworkErr = YES;
                    }
                    if (self.shouldReVerifyReceiptByServerLost(errorCodeValue)) {
                        serverLost = YES;
                    }
                    if (errorCodeValue == 20034) {
                        haveBind = YES;
                    }
                }
            }
            if (!isNetworkErr && !serverLost) {
                // 非网络问题，收据校验失败，下次网络联通后不会再次校验
                [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
                if (haveBind) {
                    tModel.transactionStatus = ZYPurchaseTransactionStatus_BindByOthers;
                    errorCodeValue = 70053;
                } else {
                    tModel.transactionStatus = ZYPurchaseTransactionStatus_ReceiptInvalid;
                    errorCodeValue = 70051;
                    
                    [self.database reVerifyReceiptsSuccess:receiptFileName];
                }
                
            } else {
                // 网络原因，收据待校验
                if (isNetworkErr) {
                    tModel.transactionStatus = ZYPurchaseTransactionStatus_ReceiptWaitVerify_NetworkLost;
                } else {
                    tModel.transactionStatus = ZYPurchaseTransactionStatus_ReceiptWaitVerify;
                }
                errorCodeValue = 70052;
            }
            [self.database updateTransactionModelStatus:tModel];
            [self responseTransactionStatusChangedInMainThread:tModel];
            NSString *eerorTip = isNetworkErr?@"网络原因导致":@"非网络原因校验失败";
            NSDictionary *notifiUserInfo = @{@"error":@(errorCodeValue),
                                             @"status":@(tModel.transactionStatus),
                                             @"orderId":tModel.orderId,
                                             @"result":eerorTip};
            [NSNotificationCenter.defaultCenter postNotificationName:ZYPurchaseTransactionStatusChanged_Notifi object:nil userInfo:notifiUserInfo];
            NSLog(@"IAP: 订单收据校验不通过： %@", eerorTip);
        }
        complete();
    }];
}
// 服务器原因导致的需要重复校验
- (BOOL(^)(NSInteger errorCode))shouldReVerifyReceiptByServerLost{
    return ^(NSInteger errorCode){
        if ((errorCode == 2) ||
            (errorCode == 20030) ||
            (errorCode == 20031) ||
            (errorCode == 20035)) {
            return YES;
        }
        return NO;
    };
}

/// 静默提交所有未成功提交的收据至后台
+ (void)uploadUnVerifyReceiptIfNeededInSilence:(nullable dispatch_block_t)complete{
    [[ZYPurchaseSaleman defaultSaleman] uploadUnVerifyReceiptIfNeededInSilence:complete];
}

static BOOL reVerifyEnable = YES;
- (void)uploadUnVerifyReceiptIfNeededInSilence:(nullable dispatch_block_t)complete{
    if (!reVerifyEnable) {
        return;
    }
    reVerifyEnable = NO;
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0f * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        reVerifyEnable = YES;
    });
    NSArray *unVerifyReceipts = [self.database fetchUnVerifyReceipts];
    if (!unVerifyReceipts || (unVerifyReceipts.count == 0)) {
        NSLog(@"IAP: 没有收据需要二次提交");
        if (complete) {
            complete();
        }
        return;
    }
        
    dispatch_group_t group = dispatch_group_create();
    for (NSInteger idx = 0; idx < unVerifyReceipts.count; idx++) {
        NSDictionary *receiptDict = unVerifyReceipts[idx];
        dispatch_group_enter(group);
        [self submitReceiptInfo:receiptDict complete:^(BOOL success, id info){
            if (success) {
                NSLog(@"IAP: 第 %ld/%ld 个收据 %@ 二次提交成功", idx, unVerifyReceipts.count, info);
            } else {
                NSLog(@"IAP: 第 %ld/%ld 个收据 二次提交失败: %@", idx, unVerifyReceipts.count, info);
            }
            dispatch_group_leave(group);
        }];
    }
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        if (complete) {
            complete();
        }
    });
}

// 提交单条收据
- (void)submitReceiptInfo:(NSDictionary *)receiptDict
                 complete:(nullable void (^)(BOOL success, id info))complete{
    
    NSString *file_name = [receiptDict zy_stringForKey:@"file_name"];
    NSString *filePath = [ZYPurchaseTransactionModel receiptDataFilePathForFileName:file_name];
    NSString *receiptString = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];
    if (!receiptString.zy_isValuable) {
        if (complete) {
            complete(NO, @"Receipt lose");
        }
        return;
    }
    NSString *orderId = [receiptDict zy_stringForKey:@"order_id"];
    NSString *customerId = ZYPurchaseSaleman.defaultSaleman.customerId;
    NSString *customerToken = ZYPurchaseSaleman.defaultSaleman.customerToken;
    NSMutableDictionary *requestDict = @{@"receipt_data": receiptString,
                                         @"deviceId":ZYPurchaseSaleman.defaultSaleman.deviceUUID}.mutableCopy;
    if (orderId.zy_isValuable) {
        requestDict[@"orderSN"] = orderId;
    }
                                  
    NSString *url = ZYPurchaseSaleman.formatPurchageUrlString(ZYPurchaseAPI_VerifyReceipt);
    // 第二步：提交收据
    [PJNetworkStation POST:url params:requestDict result:^(BOOL success, id info) {
        NSLog(@"IAP: 收据校验结果， %@ info：%@", success?@"成功":@"失败", info);
        if (success && info && [info isKindOfClass:[NSDictionary class]]) {
            NSDictionary *dataDict = info;
            NSDictionary *resultDict = @{};
            if ([dataDict.allKeys containsObject:@"result"]) {
                id resultObj = dataDict[@""];
                if ([resultObj isKindOfClass:[NSDictionary class]]) {
                    resultDict = resultObj;
                }
            }
            NSString *orderSN = [resultDict zy_stringForKey:@"orderSN"];
            if (orderSN.zy_isValuable) {
                NSDictionary *dataDict = info;
                NSString *orderSN = [dataDict zy_stringForKey:@"orderSN"];
                ZYPurchaseTransactionModel *originModel = nil;
                if (orderSN.zy_isValuable) {
                    originModel = [self.database queryTransactionModel:orderSN];
                }
                if (originModel) {
                    // 能找到订单的话更新状态
                    originModel.receipt_data_filename = file_name;
                    originModel.transactionStatus = ZYPurchaseTransactionStatus_Success;
                    [self.database updateTransactionModelStatus:originModel];
                }
            }
            NSString *orderIdInKeychain =  [ZYPurchaseDataBase lastIAPApplicationUsernameInKeychain];
            if (orderIdInKeychain && orderSN.zy_isValuable && [orderIdInKeychain containsString:orderSN]) {
                [ZYPurchaseDataBase clearLastIAPApplicationUsernameInKeychain];
            }
            if (complete) {
                complete(YES, file_name);
            }
            [self.database reVerifyReceiptsSuccess:file_name];
        } else {
            BOOL isNetworkErr = NO;
            BOOL serverLost = NO;
            NSInteger errorCodeValue = 0;
            if (info && [info isKindOfClass:[NSDictionary class]]) {
                NSDictionary *dataDict = info;
                if ([dataDict.allKeys containsObject:@"errcode"]) {
                    NSInteger errorCodeValue = [dataDict[@"errcode"] integerValue];
                    if (errorCodeValue == -9999) {
                        isNetworkErr = YES;
                    }
                    if (self.shouldReVerifyReceiptByServerLost(errorCodeValue)) {
                        serverLost = YES;
                    }
                }
            }
            if (!isNetworkErr && !serverLost) {
                // 如果不是网络原因就删掉该收据
                [self.database reVerifyReceiptsSuccess:file_name];
            }
            if (complete) {
                complete(NO, isNetworkErr?@"Network disconnect":@"Sever verify finished, receipt not pass!");
            }
        }
    }];
}

- (void(^)(NSString *preDes, SKPaymentTransaction *trans))logTransaction{
    return ^(NSString *preDes, SKPaymentTransaction *trans){
        NSDictionary *stateDesDict = @{@(SKPaymentTransactionStatePurchasing):@"Purchasing 支付中",
                                     @(SKPaymentTransactionStatePurchased):@"Purchased 支付完成",
                                     @(SKPaymentTransactionStateFailed):@"Failed 支付失败",
                                     @(SKPaymentTransactionStateRestored):@"Restored 商品已支付",
                                     @(SKPaymentTransactionStateDeferred):@"Deferred 状态待定"};
        NSString *stateDes = @"未知状态";
        if ([stateDesDict.allKeys containsObject:@(trans.transactionState)]) {
            stateDes = stateDesDict[@(trans.transactionState)];
        }
        NSString *logString = [NSString stringWithFormat:@"%@, 状态 %@ product_id %@, 交易: %@, 交易id：%@, 原始交易：%@, 原始交易id：%@", preDes, stateDes, trans.payment.productIdentifier, trans.transactionDate, trans.transactionIdentifier, trans.originalTransaction.transactionDate, trans.originalTransaction.transactionIdentifier];
        NSLog(logString);
        self.logRecord(logString);
    };
}

/// 是否是订阅类型交易
- (BOOL)isSubscribe:(SKPaymentTransaction *)transaction{
    if (transaction.payment) {
        NSString *productId = transaction.payment.productIdentifier;
        if (productId && (productId.length > 0)) {
            NSArray *sub_arr = [productId componentsSeparatedByString:@"_"];
            if (sub_arr.count > 1) {
                NSString *categoryStr = sub_arr[1];
                return [categoryStr.uppercaseString isEqualToString:@"C"];
            }
        }
    }
    return NO;
}

@end
